﻿using System;
using System.Linq;
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.DisplayManagement;
using Orchard.Settings;
using Orchard.UI.Admin;
using Orchard.UI.Navigation;
using Orchard.Users.Models;
using PmpNetwork.Services;
using PmpNetwork.ViewModels;
using Orchard.Localization;
using Orchard.UI.Notify;
using Orchard;
using Orchard.Security;
using PmpNetwork.Models;
using Orchard.Data;
using System.Collections.Generic;
using System.Web.Script.Serialization;
using PmpNetwork.Extensions;

namespace PmpNetwork.Controllers
{
    [Admin]
    public class WikiAdminController : Controller, IUpdateModel
    {
        private dynamic Shape { get; set; }
        private Localizer T { get; set; }
        private readonly IWikiArticleService _wikiService;
        private readonly ISiteService _siteService;
        private readonly IContentManager _contentManager;
        private readonly INotifier _notifier;
        private readonly ITransactionManager _transactionManager;
        private readonly IAuthenticationService _authenticationService;
        private readonly IQuestionService _questionService;
        public IOrchardServices Services { get; set; }

        public WikiAdminController(IWikiArticleService wikiService, 
            IShapeFactory shapeFactory, 
            ISiteService siteService,
            IContentManager contentManager,
            IOrchardServices services,
            ITransactionManager transactionManager,
            IAuthenticationService authenticationService,
            IQuestionService questionService,
            INotifier notifier)
        {
            Shape = shapeFactory;
            _wikiService = wikiService;
            _siteService = siteService;
            _contentManager = contentManager;
            _notifier = notifier;
            _transactionManager = transactionManager;
            _authenticationService = authenticationService;
            _questionService = questionService;
            Services = services;
            T = NullLocalizer.Instance;
        }

        public ActionResult Index(WikiSearchViewModel search, PaginationInfo paging)
        {
            var articles = _wikiService.Search(search, paging);
            var pagerShape = Shape.Pager(paging).TotalItemCount(paging.TotalRecords);

            return View(new WikiAdminViewModel
            {
                Search = search,
                Articles = articles,
                Pager = pagerShape
            });
        }

        public ActionResult Create(string name)
        {
            var article = _contentManager.New<WikiArticlePart>("WikiArticle");
            if (article == null)
                return HttpNotFound();

            dynamic model = _contentManager.BuildEditor(article);

            if (!String.IsNullOrWhiteSpace(name))
            {
                article.Name = name;
                article.NameOnUrl = UrlUtilities.UrlFriendlyString(name);
            }
            return View((object)model);
        }

        [ValidateInput(false)]
        [HttpPost, ActionName("Create")]
        public ActionResult CreatePOST()
        {
            var article = _contentManager.New<WikiArticlePart>("WikiArticle");

            _contentManager.Create(article, VersionOptions.Draft);
            dynamic model = _contentManager.UpdateEditor(article, this);

            article.AuthorId = _authenticationService.GetAuthenticatedUser().Id;

            if (!ModelState.IsValid)
            {
                _transactionManager.Cancel();
                // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
                return View((object)model);
            }

            article.CreatedDate = DateTime.Now;
            article.LastUpdatedDate = DateTime.Now;

            _contentManager.Publish(article.ContentItem);
            Services.Notifier.Information(T("Wiki article created. Now please manage the questions for the article."));
            return Redirect(Url.Action("Questions", "WikiAdmin", new { area = "PmpNetwork", id = article.Id }));
        }

        public ActionResult Edit(int id)
        {
            var article = _wikiService.Get(id);
            var model = _contentManager.BuildEditor(article);
            
            return View((object)model);
        }

        [ValidateInput(false)]
        [HttpPost, ActionName("Edit")]
        public ActionResult EditPOST(int id)
        {
            var article = _contentManager.Get<WikiArticlePart>(id, VersionOptions.DraftRequired);

            if (article == null)
                return HttpNotFound();

            dynamic model = Services.ContentManager.UpdateEditor(article, this);
            if (!ModelState.IsValid)
            {
                Services.TransactionManager.Cancel();
                // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
                return View((object)model);
            }

            article.LastUpdatedDate = DateTime.Now;

            _contentManager.Publish(article.ContentItem);
            Services.Notifier.Information(T("Wiki article updated"));

            return Redirect(Url.Action("Index", "WikiAdmin", new { area = "PmpNetwork" }));
        }

        public ActionResult Questions(int id)
        {
            ViewBag.ArticleId = id;
            ViewBag.Questions = _questionService.GetQuestionsForArticle(id);
            return View();
        }

        [ValidateInput(false)]
        [HttpPost, ActionName("Questions")]
        public ActionResult QuestionsPOST(int id, FormCollection data)
        {
            JavaScriptSerializer js = new JavaScriptSerializer();
            var questions = js.Deserialize<IList<QuestionViewModel>>(data["data"]);

            if (questions != null && questions.Count > 0)
            {
                _questionService.SaveQuestions(id, questions);
            }
            return Questions(id);
        }

        bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties)
        {
            return TryUpdateModel(model, prefix, includeProperties, excludeProperties);
        }

        void IUpdateModel.AddModelError(string key, LocalizedString errorMessage)
        {
            ModelState.AddModelError(key, errorMessage.Text);
        }
    }
}